/*	Renegade Scripts.dll
	Example Plugin Code
	Copyright 2007 Whitedragon(MDB), Jonathan Wilson

	This file is part of the Renegade scripts.dll
	The Renegade scripts.dll is free software; you can redistribute it and/or modify it under
	the terms of the GNU General Public License as published by the Free
	Software Foundation; either version 2, or (at your option) any later
	version. See the file COPYING for more details.
	In addition, an exemption is given to allow Run Time Dynamic Linking of this code with any closed source module that does not contain code covered by this licence.
	Only the source code to the module(s) containing the licenced code has to be released.
*/



/************************************** Polite Request ***************************************
** I have put a lot of time and effort into YaRR. If you want to use some of the source     **
** please tell me. Anything used from YaRR must be open source, as is scripts.dll.          **
***************************************** Thank you *****************************************/


#include "YaRRIncludes.h"

FILE *ScopeLog::f = 0;
int ScopeLog::level = 0;
int ScopeLog::ref = 0;
DWORD ScopeLog::thread = 0;

#ifdef _YaRRDebug
ScopeLog glog("Global", 0);
#endif

unsigned int GetHostName(void *id)
{
	const char *IP = Get_IP_Address(*(int *)id);
	if(!IP)
	{
		return 0;
	}
	Stacker<char *> result;
	const char *ret = YaRRTrace::Trace(IP, &result);
	
	EnterCriticalSection(&YaRRPlayers::Mutex);
	Player *p = YaRRPlayers::Find(*(int *)id);
	if(!p)
	{	
		return 0;
		LeaveCriticalSection(&YaRRPlayers::Mutex);
	}	
	
	char *tmp[256];
	int i = 0;
	if(ret)
	{
		IRC::SendC('a', "%s", ret);
		YaRRFunctions::DeleteList(&result);
		CDealloc(ret);
		delete []IP;
		*p->Node = 0;
		LeaveCriticalSection(&YaRRPlayers::Mutex);
		return 0;
	}
	else
	{
		IterateStack(x, char *, (&result))
		{
			if(x)
			{
				tmp[i++] = x;
			}
		}
	}

	for(int z = i-1; z >= 0; z--)
	{
		if(strcmp(tmp[z], IP) != 0)
		{
			if(strcmp(tmp[z], "TimeOut") != 0)
			{
				IRC::SendC('a', "%S's node is: %s", Get_Wide_Player_Name_By_ID(*(int *)id), tmp[z]);
				strcpy(p->Node, tmp[z]);
				YaRRFunctions::DeleteList(&result);
				YaRRFunctions::CheckNodeBan(p);
				delete []IP;
				LeaveCriticalSection(&YaRRPlayers::Mutex);
				return 0;
			}
		}
	}
	YaRRFunctions::DeleteList(&result);
	IRC::SendC('a', "%S's IP is: %s", Get_Wide_Player_Name_By_ID(*(int *)id), IP);
	delete []IP;
	*p->Node = 0;
	LeaveCriticalSection(&YaRRPlayers::Mutex);
	return 0;
}


void ObjectCreate(void *stub, GameObject *o)
{
	DLOG;
	YaRRCrate::ObjectCreated(o);
	if(stricmp(Commands->Get_Preset_Name(o), "Invisible_Object") == 0)
	{
		Vector3 pos = Commands->Get_Position(o);
		for(GenericSLNode *x = BaseGameObjList->HeadNode; x != 0; x = x->NodeNext)
		{
			GameObject *obj = (GameObject *)x->NodeData;
			if(obj && As_BeaconGameObj(obj) != 0)
			{
				Vector3 objp = Commands->Get_Position(obj);
				if((pos.X == objp.X) && (pos.Y == objp.Y))
				{
					o = obj;
					break;
				}
			}
		}
	}

	if(Commands->Is_A_Star(o) && Is_Soldier(o))
	{
		Attach_Script_Once(o, "YaRRPlayer", "");
		Attach_Script_Once(o, "YaRRVeteran", "");
	}
	else if(Is_Vehicle(o))
	{
		Attach_Script_Once(o, "YaRRVehicle", "");
	}
	else if(Is_Beacon(o))
	{
		Attach_Script_Once(o, "YaRRBeacon",  "");
	}
	else if(Is_C4(o))
	{
		Attach_Script_Once(o, "YaRRC4", "");
	}
}

float BHS_Versions[128];

void VersionHook(int PlayerID,float Version)
{
	DLOG;
	BHS_Versions[PlayerID] = Version;
}

int Purchase_Hook(BaseControllerClass *base,GameObject *purchaser,unsigned int cost,unsigned int preset,const char *data)
{
	DLOG;
	Player *p = YaRRPlayers::Find(Get_Player_ID(purchaser));
	if(!p)
	{
		return -1;
	}

	if(data[0] == '0')
	{
		if(p->BlockBeacons == 1)
		{
			YaRRFunctions::PPage(p->ID, "You have been blocked from buying beacons.");
			return 1;
		}
	}
	else if(data[0] == '1')
	{
		if(p->BlockCharacters == 1)
		{
			YaRRFunctions::PPage(p->ID, "You have been blocked from buying characters.");
			return 1;
		}
	}
	else if(data[0] == '2')
	{
		if(p->BlockVehicles == 1)
		{
			YaRRFunctions::PPage(p->ID, "You have been blocked from buying vehicles.");
			return 1;
		}
	}	
	return -1;
	
}	

void Purchase_Mon_Hook(BaseControllerClass *base,GameObject *purchaser,unsigned int cost,unsigned int preset, unsigned int purchaseret, const char *data)
{
	DLOG;
	if(YaRRGlobal::NoOutput)
	{
		return;
	}
	if(purchaseret == 0)
	{
		const char *t = WideCharToChar(Translate_Preset_ID_To_PT_String_Name(base->team,preset));
		const char *p = YaRRFunctions::strdup2(t);
		delete []t;
		if(strcmp(p, "No String") == 0)
		{
			p = YaRRFunctions::GetPresetScreenName(Get_Definition_Name(preset));
		}
		YaRRVeteran::Purchased(Get_Definition_Name(preset), atoi(data), Get_Player_ID(purchaser));
		IRC::SendC('a', "\x03%d%S bought a%s %s\x03", Get_Team(Get_Player_ID(purchaser)) == 0 ? 4 : 8, Get_Wide_Player_Name(purchaser), YaRRFunctions::Vowel(p[0]) == 1 ? "n" : "", p);
		CDealloc(p);
	}
}



void Plugin_Load()
{
	DLOG;
	YaRRMemory::Load();

#ifdef _YaRRDebug
	YaRRMemory::LogMemory(1);
#endif
	YaRRGlobal::Startup();
	YaRRStrings::Startup();
	YaRRSettings::Load();
	IRC::Load();
	YaRRDatabase::Startup();
	YaRRPlayers::Startup();
	YaRRWorker::Startup();
	YaRRTrace::Startup();
	YaRRCrate::Startup();
	YaRRVeteran::Startup();
	YaRRCommands::Startup();
	

	ObjectCreateHookStruct *ochs = new ObjectCreateHookStruct;
	ochs->data = 0;
	ochs->hook = ObjectCreate;
	AddObjectCreateHook(ochs);
	AddVersionHook(VersionHook);

	memset((void *)BHS_Versions, 0, 128*sizeof(float));

	YaRRHooking::Install();

	if(YaRRSettings::NoPending == 1)
	{
		YaRRFunctions::ApplyNoPendingPatch();
	}
	if(YaRRSettings::StartButtonFix == 1)
	{
		YaRRFunctions::ApplyStartButtonFix();
	}
	AddPowerupPurchaseHook(Purchase_Hook, "0");
	AddCharacterPurchaseHook(Purchase_Hook, "1");
	AddVehiclePurchaseHook(Purchase_Hook, "2");

	AddPowerupPurchaseMonHook(Purchase_Mon_Hook, "0");
	AddCharacterPurchaseMonHook(Purchase_Mon_Hook, "2");
	AddVehiclePurchaseMonHook(Purchase_Mon_Hook, "1");	
}



void Plugin_Unload() 
{
	DLOG;
	YaRRCommands::Shutdown();
	YaRRVeteran::Shutdown();
	YaRRCrate::Shutdown();
	YaRRTrace::Shutdown();
	YaRRWorker::Shutdown();
	YaRRHooking::Uninstall();
	YaRRPlayers::Shutdown();
	YaRRDatabase::Shutdown();
	
	IRC::Unload();
	YaRRSettings::Unload();
	YaRRGlobal::Shutdown();
	YaRRMemory::Unload();
}

extern "C" {

char *MapName = 0;

DLLEXPORT void SSGM_Chat_Hook(int ID, int Type, const wchar_t *Msg) 
{
	DLOG;
}

DLLEXPORT void SSGM_Host_Hook(int ID, int Type, const char *Msg) 
{
	DLOG;
	if(Type != 0)
	{
		return;
	}
	if(YaRRGlobal::NoOutput && *Msg != '(')
	{
		return;
	}
	IRC::SendC('b', "\x03%dHost:\x03 %s", 14, Msg);

}

DLLEXPORT void SSGM_Player_Join_Hook(int ID, const char *Nick) 
{
	DLOG;
	if(BHS_Versions[ID] < YaRRSettings::Minimum_BHS)
	{
		YaRRFunctions::BootPlayer(ID, "The minimum required custom scripts.dll is %.2f. Please get it at www.game-maps.net", YaRRSettings::Minimum_BHS);
		BHS_Versions[ID] = 0;
		return;
	}
	const char *ip = Get_IP_Address(ID);
	bool IsNickB = YaRRFunctions::IsNickBanned(Nick);
	bool IsIPB = YaRRFunctions::IsIPBanned(ip);
	if(IsNickB || IsIPB)
	{
		YaRRFunctions::BanInfo ifo;
		YaRRFunctions::GetBanInfo(&ifo, Nick, ip);
		YaRRFunctions::ConsoleInputF("msg %s was banned for %s\n", Nick, ifo.Reason);
		YaRRFunctions::BootPlayer(ID, "You were banned by %s for: %s", ifo.Banner, ifo.Reason);

		if((IsNickB && !IsIPB) || (!IsNickB && IsIPB))
		{
			YaRRDatabase::Query(0, "INSERT INTO Bans(Nick, IP, WhoBy, Reason, Time) VALUES ('%q', '%q', '%q', '%q', %d);", Nick, ip, ifo.Banner, ifo.Reason, ifo.Time);
		}
		BHS_Versions[ID] = 0;
		return;
	}	

	IRC::SendC('b', "\x03%d%s\x03%d has joined the game.", (Get_Team(ID) == 0 ? 4 : 8), Nick, 3);

	Stacker<YaRRDatabase::Row *> Result;
	YaRRDatabase::Query(&Result, "SELECT * FROM Players WHERE Nick = '%q';", Nick);
	if(Result.Empty())
	{
		char hex[64];
		YaRRFunctions::RGBToHex(YaRRSettings::MessageColour, hex);
		YaRRDatabase::Query(0, "INSERT INTO Players(Nick, JOINMSG, PPageC, PPageS) VALUES('%q', '', '%s', '%s');", Nick, hex, YaRRSettings::PPageSound);
	}
	else
	{
		if(strcmp(YaRRDatabase::GetColumnData("JOINMSG", Result[0]->Columns), "") != 0)
		{
			YaRRFunctions::ConsoleInputF("msg [%s]: %s", Nick, YaRRDatabase::GetColumnData("JOINMSG", Result[0]->Columns));
		}

	}

	YaRRDatabase::DeleteResult(&Result);
	delete []ip;

	YaRRPlayers::Joined(ID);
	Player *p = YaRRPlayers::Find(ID);
	if(!p)
	{
		BHS_Versions[ID] = 0;
		return;
	}
	else
	{
		p->BHS = BHS_Versions[ID];
		BHS_Versions[ID] = 0;
	}
	Task GetHost;
	GetHost.CALL = GetHostName;
	strcpy(GetHost.Name, "CALL");
	GetHost.Param = CAlloc(4);
	*(int *)GetHost.Param = ID;
	GetHost.Count = 1;
	YaRRWorker::Addtask(GetHost);

	YaRRVeteran::PlayerJoined(ID);
}

DLLEXPORT void SSGM_Player_Leave_Hook(int ID) 
{
	DLOG;
	IRC::SendC('b', "%c%d%S %c3has left the game.", 3, (Get_Team(ID) == 0 ? 4 : 8), Get_Wide_Player_Name_By_ID(ID), 3);
	YaRRPlayers::Leave(ID);
}

DLLEXPORT void SSGM_Level_Loaded_Hook() 
{
	DLOG;
	YaRRGlobal::Mapload();
	YaRRPlayers::MapLoad();
	YaRRSettings::MapLoad(The_Game()->MapName);
	
	Attach_Script_Building("YaRRBuilding", "", 2);

	if(!YaRRGlobal::NoOutput)
	{
		IRC::SendC('b', "%c3%s has loaded.", 3, The_Game()->MapName);
	}
	if(MapName)
	{
		CDealloc(MapName);
	}
	MapName = YaRRFunctions::strdup2(The_Game()->MapName);

	GameObject *o = Commands->Create_Object("Invisible_Object", Vector3(0.0, 0.0, 0.0));
	Attach_Script_Once(o, "IRCThinkScript", "");

	int Chance = Commands->Get_Random_Int(0, 100);
	if(Chance > YaRRSettings::DefenceChance)
	{
		Commands->Send_Custom_Event(0,o,101,0,0);
		return;
	}

	Commands->Send_Custom_Event(0,o,100,0,0);

	IterateStack(pos, Vector3, YaRRSettings::GDIDefences)
	{
		GameObject *o = Commands->Create_Object("gdi_guard_tower", pos);
		if(o)
		{
			Attach_Script_Once(o, "YaRRDefenceRebuy", "");
		}
	}

	IterateStack(pos2, Vector3, YaRRSettings::NodDefences)
	{
		GameObject *o = Commands->Create_Object("nod_turret_mp_improved", pos2);
		if(o)
		{
			Attach_Script_Once(o, "YaRRDefenceRebuy", "");
		}
	}	
}

DLLEXPORT void SSGM_GameOver_Hook() 
{
	DLOG;
	YaRRGlobal::Mapend();
	if(!YaRRGlobal::NoOutput)
	{
		char Win[256];
		sprintf(Win, "\x03%d%S has won the game by ", 3, Get_Wide_Team_Name(Get_Team(The_Game()->WinnerID)));
		unsigned int type = The_Game()->WinType;
	
		if (type == 0)
		{
			strcat(Win,"server shutdown.");
		}
		else if (type == 2)
		{
			strcat(Win,"high score when time limit expired.");
		}
		else if (type == 3)
		{
			strcat(Win,"base destruction.");
		}
		else if (type == 4)
		{
			strcat(Win,"a pedestal beacon.");
		}
		IRC::SendC('b', "%s", Win);
		IRC::SendC('b', "\x03%dNod %.0f points\x03%d : \x03%dGDI %.0f points\x03%d : MVP: \x03%d%S*%d", 4, Get_Team_Score(0), 3, 8, Get_Team_Score(1), 3, Get_Team(The_Game()->WinnerID) == 0 ? 4 : 8, (const wchar_t *)The_Game()->MVPName, The_Game()->MVPCount);
		IRC::SendC('b', "%c3%s has ended. Next map will be %s.", 3, MapName, The_Game()->MapName);
	}
	//YaRRPlayers::UpdateDatabase(0);
}

DLLEXPORT void SSGM_Console_Output_Hook(const char *Output) 
{
	DLOG;
}

DLLEXPORT bool SSGM_DDE_Hook(const char *DDE) 
{
	DLOG;
	return true;
}

}